//
//  mttImage.m
//  mtt
//
//  Created by Gerfried Mikusch on 13.07.10.
//  Copyright 2010 __MyCompanyName__. All rights reserved.
//

#import <QuartzCore/QuartzCore.h>
#import "mttImage.h"
#import "mttPoint.h"

CGFloat GetDistanceBetweenTwoPoints(CGPoint point1,CGPoint point2)
{
	
	//Berechnet die Distanz zwischen zwei punkten
	//d = sqrt((p1.x - p2.x)^2 + (p1.y - p2.y)^2)
	
	
	CGFloat dx = point1.x - point2.x;
	CGFloat dy = point1.y - point2.y;
	return sqrt(dx*dx + dy*dy);
};


@implementation mttImage


@synthesize tapRecognizer, tapRecTwoFingers, longPressRecognizer, panRecognizer, rotationRecognizer, pinchRecognizer, pinPoints, delegate, imagekey;

int pinPointKey = 0;
CGPoint hitPointWindow;
CGFloat pinRotAngle;


#pragma mark -
#pragma mark hit-Testing


-(UIView *) hitTest:(CGPoint)point withEvent:(UIEvent *)event {
	
	
	NSArray *mySubviews = [self subviews];
	if (mySubviews != nil) {
		
		for (int i=mySubviews.count-1; i>=0; i--) {
			
			mttPoint *actSub = [mySubviews objectAtIndex:i];
			
			//CGPoint receiverPoint = [self convertPoint:point toView:actSub];
			
			if ( [self isPoint:point inRect:actSub.frame]) {
				return actSub;
				
			}
			

		}
		
		
		
	}
	
	//HitTest on non-Transparent pixels
	CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
	CGBitmapInfo info = kCGImageAlphaPremultipliedLast;
	
	UInt32 bitmapData[1];
	bitmapData[0] = 0;
	
	
	
	CGContextRef context = CGBitmapContextCreate(bitmapData, 1, 1, 8, 4, colorspace, info);
	CGRect rect = CGRectMake(-point.x, point.y - CGImageGetHeight(self.image.CGImage), CGImageGetWidth(self.image.CGImage), CGImageGetHeight(self.image.CGImage));
	
	CGContextDrawImage(context, rect, self.image.CGImage);
	CGContextFlush(context);
	
	if (bitmapData[0] != 0) {
		CGContextRelease(context);
		CGColorSpaceRelease(colorspace);
		return self;
	} else {
		return nil;
	}
	
}

-(BOOL)isPoint:(CGPoint)point inRect:(CGRect)rect {

	if (point.x >= rect.origin.x && 
		point.x <= (rect.origin.x + rect.size.width) && 
		point.y >= rect.origin.y && 
		point.y <= (rect.origin.y + rect.size.width)) 
	{
		return YES;
	} else {
		return NO;
	}
	
}


#pragma mark -
#pragma mark position & point operations

-(void)setAnchorPointBetweenFirstLocation:(CGPoint)firstLocation andSecondLocation:(CGPoint)secondLocation {
	
	
	CGFloat minX;
	CGFloat maxX;
	CGFloat minY;
	CGFloat maxY;
	
	//Welcher der X bzw. Y Werte ist der kleine. Notwendig für die berechnung des Mittelpunkts
	if (firstLocation.x < secondLocation.x) {
		minX = firstLocation.x;
		maxX = secondLocation.x;
	} else {
		minX = secondLocation.x;
		maxX = firstLocation.x;
	}
	
	if (firstLocation.y < secondLocation.y) {
		minY = firstLocation.y;
		maxY = secondLocation.y;
	} else {
		minY = secondLocation.y;
		maxY = firstLocation.y;
	}
	
	//Berechne Mittelpunkt der beiden touches
	CGFloat newX = minX + (maxX-minX)/2;
	CGFloat newY = minY + (maxY-minY)/2;
	CGPoint newCenter = CGPointMake(newX, newY);
	//NSLog(@"newCenter x:%f, y:%f", newCenter.x, newCenter.y);
	
	
	//Den neuen Mittelpunkt in das Koordinatensystem der Superview konvertieren
	CGPoint newCenterConverted = [self convertPoint:newCenter toView:self.superview];
	//NSLog(@"convertedCenter x:%f, y:%f", newCenterConverted.x, newCenterConverted.y);
	
	//Den neuen Mittelpunkt normalisieren
	CGPoint normNewCenter = CGPointMake(newCenter.x/self.bounds.size.width, newCenter.y/self.bounds.size.height);
	//NSLog(@"normCenter x:%f, y:%f", normNewCenter.x, normNewCenter.y);
	
	
	
	
	//NSLog(@"oldLayerPosition x:%f, y:%f", self.layer.position.x, self.layer.position.y);
	
	
	//Ankerpunkt und neue Position setzen
	self.layer.anchorPoint = normNewCenter;
	
	//Position des Layers neu setzen, da die änderung des anchorpoints diese auch verändert, also wieder zurücksetzen
	self.layer.position = newCenterConverted;
	//NSLog(@"NewlayerPosition x:%f, y:%f", self.layer.position.x, self.layer.position.y);
	
}

-(void)setAnchorpointTo:(CGPoint) point {
	
	
	//Den neuen Mittelpunkt in das Koordinatensystem der Superview konvertieren
	CGPoint newCenterConverted = [self convertPoint:point toView:self.superview];
	//NSLog(@"convertedCenter x:%f, y:%f", newCenterConverted.x, newCenterConverted.y);
	
	//Den neuen Mittelpunkt normalisieren
	CGPoint normNewCenter = CGPointMake(point.x/self.bounds.size.width, point.y/self.bounds.size.height);
	//NSLog(@"normCenter x:%f, y:%f", normNewCenter.x, normNewCenter.y);

	
	//NSLog(@"oldLayerPosition x:%f, y:%f", self.layer.position.x, self.layer.position.y);
	
	
	//Ankerpunkt und neue Position setzen
	self.layer.anchorPoint = normNewCenter;
	
	//Position des Layers neu setzen, da die änderung des anchorpoints diese auch verändert, also wieder zurücksetzen
	self.layer.position = newCenterConverted;
	//NSLog(@"NewlayerPosition x:%f, y:%f", self.layer.position.x, self.layer.position.y);
	
	NSLog(@"------------- Anchorpoint set at Image: %@", self.imagekey);

}


-(void) willMoveToSuperview:(UIView *)newSuperview {
	
	// Das Bild richtig positionieren
	
	
	UIView *actualSuperview = [self superview];
	
	//Ausgaben zu Kontrolle
	//NSLog(@"actualSuperView x:%f, y:%f, w:%f, h:%f", actualSuperview.frame.origin.x, actualSuperview.frame.origin.y, actualSuperview.frame.size.width, actualSuperview.frame.size.height);
	//NSLog(@"ImageFrame before x:%f, y:%f, w:%f, h:%f", self.frame.origin.x, self.frame.origin.y, self.frame.size.width, self.frame.size.height);
	//NSLog(@"imagePosition before x:%f, y:%f", self.layer.position.x, self.layer.position.y);
	//NSLog(@"newSuperView x:%f, y:%f, w:%f, h:%f", newSuperview.frame.origin.x, newSuperview.frame.origin.y, newSuperview.frame.size.width, newSuperview.frame.size.height);
	//Position ist in der Mitte des bildes
	
	//Nur wenn das Bild aus dem maincontroller kommt
	
	/*
	if (actualSuperview == [delegate getView]) {
		CGFloat newX = self.layer.position.x - newSuperview.frame.origin.x;
		CGFloat newY = self.layer.position.y - newSuperview.frame.origin.y;
		
		self.layer.position = CGPointMake(newX, newY);
	}
	*/
	
	//self.center = [newSuperview convertPoint:self.center fromView:[self superview]];
	//CGPoint centerAct = self.center;
	//CGPoint centerConv = [actualSuperview convertPoint:centerAct fromView:newSuperview];
	
	//NSLog(@"centerAct x:%f, y:%f", centerAct.x, centerAct.y);
	//NSLog(@"centerConv x:%f, y:%f", centerConv.x, centerConv.y);
	
	/*CGPoint offsetX;
	
	if (newSuperview.origin.x >= actualSuperview.origin.x) {
		offsetX = newSuperview.origin.x - actualSuperview.origin.x;
	} else {
		offsetX = actualSuperview.origin.x - newSuperview.origin.x;
	}
	 */
	
	
	CGFloat offsetX = newSuperview.frame.origin.x - actualSuperview.frame.origin.x;
	CGFloat offsetY = newSuperview.frame.origin.y - actualSuperview.frame.origin.y;
	
	CGFloat newX = self.layer.position.x - offsetX;
	CGFloat newY = self.layer.position.y - offsetY;
	
	self.layer.position = CGPointMake(newX, newY);

	
}


-(mttPoint *)getNearestPinToPoint:(CGPoint)point {
	
	//Berechnet die Distanz zwischen point und den pins und gibt den nähesten zurück
	
	mttPoint *nearestPin = nil;
	
	//Angefangen bei irgendeinem pin
	NSArray *values = [pinPoints allValues];
	if ([values count] != 0)
		nearestPin = [values objectAtIndex:0];
	
	//mttPoint *anyPin = [pinPoints anyObject];
	
	CGFloat minDist =  GetDistanceBetweenTwoPoints(point, nearestPin.pinLoc);
	
	for (id key in pinPoints) {
		mttPoint *actualPin = [pinPoints objectForKey:key];
		
		CGFloat dist = GetDistanceBetweenTwoPoints(point, actualPin.pinLoc);
		if (dist < minDist) {
			minDist = dist;
			nearestPin = actualPin;
		}
		
	}
	
	return nearestPin;
	
}



#pragma mark -
#pragma mark gesture recognizing

// Ein TAP bringt das bild nach vorne!
- (void)handleTap:(UITapGestureRecognizer *)recognizer {
	if (recognizer.state == UIGestureRecognizerStateRecognized) {
		[delegate bringViewToFront:self];
		[delegate bringOptionViewToFront];
	}
}

// Touch and hold bring das menü!
-(void)handleLongPress:(UILongPressGestureRecognizer *)recognizer {
	[delegate bringViewToFront:self];
	[delegate bringOptionViewToFront];
	
	if (recognizer.state == UIGestureRecognizerStateBegan) {
		
		/*UIActionSheet *longTapMenu = [[UIActionSheet alloc] initWithTitle:nil 
																 delegate:self 
														cancelButtonTitle:nil 
												   destructiveButtonTitle:nil 
														otherButtonTitles:@"Pin", @"Set as Background", @"Remove", nil];
		*/
		
		UIActionSheet *longTapMenu = [[UIActionSheet alloc] initWithTitle:nil delegate:self cancelButtonTitle:nil destructiveButtonTitle:nil otherButtonTitles:nil];
		
		CGPoint hitPoint = [recognizer locationInView:self];
		
		/*Nur wenn ein Pin möglich ist*/
		if ([delegate isPinPossible:self.imagekey atPoint:hitPoint]) [longTapMenu addButtonWithTitle:@"Pin"];
		[longTapMenu addButtonWithTitle:@"Set as Background"];
		[longTapMenu addButtonWithTitle:@"Remove"];
		

		hitPointWindow = [recognizer locationInView:nil];
		
		NSLog(@"ImageID: %@", self.imagekey);
		NSLog(@"PinPoint beim antippen - Window: x:%f, y:%f", hitPointWindow.x, hitPointWindow.y);
		NSLog(@"PinPoint beim antippen - Image: x:%f, y:%f", hitPoint.x, hitPoint.y);
		
		//NSLog(@"hitPoint: x: %f, y: %f", hitPoint.x, hitPoint.y);
		[longTapMenu showFromRect:CGRectMake(hitPoint.x, hitPoint.y, 10, 10) inView:self animated:YES];
		[longTapMenu release];
		
	}
}


// Bewegt das Bild
-(void)handlePan:(UIPanGestureRecognizer *)recognizer {
	[delegate bringViewToFront:self];
	[delegate bringOptionViewToFront];
	
	if (recognizer.state == UIGestureRecognizerStateBegan || recognizer.state == UIGestureRecognizerStateChanged) {
		
		CGPoint translation = [recognizer translationInView:self.superview];
		[self setCenter:CGPointMake(self.center.x + translation.x, self.center.y + translation.y)];
		[recognizer setTranslation:CGPointZero inView:self.superview];
		 
	}
	
}


// Rotiert das Bild
- (void)handleRotation:(UIRotationGestureRecognizer *)recognizer {
	[delegate bringViewToFront:self];
	[delegate bringOptionViewToFront];
	
	//Ankerpunkt neu setzen
	if ([recognizer state] == UIGestureRecognizerStateBegan) {
		//NSLog(@"RotationBegan");
		//Position der Touches ermitteln
		CGPoint firstLocation = [recognizer locationOfTouch:0 inView:self];
		CGPoint secondLocation = [recognizer locationOfTouch:1 inView:self];
		//NSLog(@"fistTouch x:%f, y:%f", firstLocation.x, firstLocation.y);
		//NSLog(@"secondTouch x:%f, y:%f", secondLocation.x, secondLocation.y);
		
		//set new anchorpoint
		[self setAnchorPointBetweenFirstLocation:firstLocation andSecondLocation:secondLocation];
	}
	
    if ([recognizer state] == UIGestureRecognizerStateBegan || [recognizer state] == UIGestureRecognizerStateChanged) {
        self.transform = CGAffineTransformRotate(self.transform, [recognizer rotation]);
        [recognizer	setRotation:0];
    }
	
	if([recognizer state] == UIGestureRecognizerStateEnded) {
		
		CGPoint point = CGPointMake(self.bounds.size.width, self.bounds.size.height);
		
		[self setAnchorPointBetweenFirstLocation:self.bounds.origin andSecondLocation:point];		
	}
	
}

// Skaliert das Bild
- (void)handlePinch:(UIPinchGestureRecognizer *) recognizer {
	[delegate bringViewToFront:self];
	[delegate bringOptionViewToFront];
	
	//Ankerpunkt neu setzen
	if ([recognizer state] == UIGestureRecognizerStateBegan) {
		//NSLog(@"RotationBegan");
		//Position der Touches ermitteln
		CGPoint firstLocation = [recognizer locationOfTouch:0 inView:self];
		CGPoint secondLocation = [recognizer locationOfTouch:1 inView:self];
		//NSLog(@"fistTouch x:%f, y:%f", firstLocation.x, firstLocation.y);
		//NSLog(@"secondTouch x:%f, y:%f", secondLocation.x, secondLocation.y);
		
		//set new anchorpoint
		[self setAnchorPointBetweenFirstLocation:firstLocation andSecondLocation:secondLocation];
	}
	
	if (recognizer.state == UIGestureRecognizerStateBegan || recognizer.state == UIGestureRecognizerStateChanged) {
		self.transform = CGAffineTransformScale(self.transform, recognizer.scale, recognizer.scale);
		recognizer.scale = 1;
	}
	
	if([recognizer state] == UIGestureRecognizerStateEnded) {
		
		CGPoint point = CGPointMake(self.bounds.size.width, self.bounds.size.height);
		
		[self setAnchorPointBetweenFirstLocation:self.bounds.origin andSecondLocation:point];
		
	}
}



- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer{
    return YES;
}


- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
    
	// Pan, Pinch und Rotation sollen simultan laufen. Man könnte auch darüber nachdenken das draggen mit zwei fingern zu ermöglichen!
	if (gestureRecognizer == self.pinchRecognizer ||
		gestureRecognizer == self.rotationRecognizer ||
		gestureRecognizer == self.panRecognizer ||
		otherGestureRecognizer == self.pinchRecognizer ||
		otherGestureRecognizer == self.rotationRecognizer ||
		otherGestureRecognizer == self.panRecognizer) {
		return YES;
	}
	return NO;
}

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch{
		return YES;
}

-(void)setGestureRecognizersEnabled:(BOOL)enabled {

	
	//TODO: #2 Alle ausser dem pinRotationRecognizer ausschalten
	
	[self.tapRecognizer setEnabled:enabled];
	[self.tapRecTwoFingers setEnabled:enabled];
	[self.longPressRecognizer setEnabled:enabled];
	[self.panRecognizer setEnabled:enabled];
	[self.rotationRecognizer setEnabled:enabled];
	[self.pinchRecognizer setEnabled:enabled];
	
	
	
	
	
	
	//Alte Variante
	/*
	NSArray *imgRecognizers	= self.gestureRecognizers;
	for (int i=0; i<imgRecognizers.count; i++) {
		[(UIGestureRecognizer *)[imgRecognizers objectAtIndex:i] setEnabled:enabled];
	}
	*/
}

#pragma mark -
#pragma mark Actions & Transformations

-(void)actionSheet:(UIActionSheet *)longTapMenu clickedButtonAtIndex:(NSInteger)buttonIndex {
	
	if ([longTapMenu numberOfButtons] == 2) {
	
		switch (buttonIndex) {
			
				//Set Background
			case 0:
				[delegate setMttBackground:self];
				[self removeFromSuperview];
				break;
			
				//Remove Image
			case 1:
				[self removeFromSuperview];
				[delegate removeImage:imagekey];
				break;

		}
	}
	
	if ([longTapMenu numberOfButtons] == 3) {
		
		switch (buttonIndex) {
				
				//Pin Button
			case 0:
				
				[delegate performPinOnImages:hitPointWindow withCallerId:self.imagekey];
				
				break;
				
				//Set Background
			case 1:
				[delegate setMttBackground:self];
				[self removeFromSuperview];
				break;
				
				//Remove Image
			case 2:
				[self removeFromSuperview];
				[delegate removeImage:imagekey];
				break;
				
		}
	}
}


-(void)setPin:(mttPoint *)pin atPoint:(CGPoint)point {
	
	NSLog(@"----------------- pinID in setPin: %i", pin.pinID);
	pin.pinLoc = [self convertPoint:point fromView:nil];
	
	pin.layer.position = pin.pinLoc;
	
	[pinPoints setObject:pin forKey:[NSNumber numberWithInt:pin.pinID]];
	
	
	
	[self addSubview:pin];
	
	/*
	//Kurzer fade Out des pins
	CABasicAnimation *fade = [CABasicAnimation animationWithKeyPath:@"opacity"];
	fade.duration = 0.75;
	fade.delegate = pin;
	fade.fromValue = [NSNumber numberWithFloat:1.0];
	
	fade.repeatCount = 0;
	fade.removedOnCompletion = NO;
	//fade.autoreverses = NO;
	[pin.layer addAnimation:fade forKey:nil];
	
	pin.layer.opacity = 0.0;
	*/
		
}

-(void)deletePin:(int)deletePinID {
	
	
	NSArray* mySubviews = self.subviews;
	
	for (int i=0; i<[mySubviews count]; i++) {
		mttPoint *actualSubview = [mySubviews objectAtIndex:i];
		if (actualSubview.pinID == deletePinID) {
			[actualSubview removeFromSuperview];

		}
	}
	
	
	[self.pinPoints removeObjectForKey:[NSNumber numberWithInt:deletePinID]];
	
	/*
	for (int i=0; i<[pinPoints count]; i++) {
		NSLog(@"PinID bla: %@", [pinPoints  objectForKey:[NSNumber numberWithInt:i]]);
	}
	 */
	
}

-(BOOL)isPinInImage:(int)thisPinID {
	
	
	for (id key in pinPoints) {
		mttPoint* actualPin = [pinPoints objectForKey:key];
		if (actualPin.pinID == thisPinID) return YES;
	}
	
	return NO;
	
}

-(void)logPinPoints:(NSNumber *) key {
	
	NSLog(@"PinPoints for Image: %@", key);
	for (id key in pinPoints) {
		mttPoint *actualPoint = [pinPoints objectForKey:key];
		NSLog(@"PinPoint: %i", actualPoint.pinID);
	}
	
}


#pragma mark -
#pragma mark visibility

-(void)hideSubviews:(BOOL)hide {
	
	CGFloat visible = 1.0;
	CGFloat unvisible = 0.0;
	
	//Pins werden ein bzw. ausgefadet
	for (int i=0; i<self.subviews.count; i++) {
		mttPoint *actualPoint = [self.subviews objectAtIndex:i];
		
		CABasicAnimation *fade = [CABasicAnimation animationWithKeyPath:@"opacity"];
		fade.duration = 0.5;
		fade.delegate = actualPoint;
		if (hide) fade.fromValue = [NSNumber numberWithFloat:visible];
		if (!hide) fade.fromValue = [NSNumber numberWithFloat:unvisible];
		
		fade.repeatCount = 0;
		fade.removedOnCompletion = NO;
		//fade.autoreverses = NO;
		[actualPoint.layer addAnimation:fade forKey:nil];
		
		if (hide) actualPoint.layer.opacity = unvisible;
		if (!hide) actualPoint.layer.opacity = visible;
	}
	
}


#pragma mark -
#pragma mark init & dealloc

- (id)initWithImage:(UIImage *)image {
	[super initWithImage:image];
	
	[self setUserInteractionEnabled:YES];
	[self setMultipleTouchEnabled:YES];
	
	[self setAutoresizesSubviews:NO];
	
	//Bug #1 geht nur wenn in der Gruppe tatsächlich die Bounds angesprochen werden.
	[self setAutoresizingMask:	UIViewAutoresizingNone];
		
	pinPoints = [[NSMutableDictionary alloc] init];
	
	//UIGestureRecognizer *recognizer;
	
	//recognizer für taps mit einem Finger
	self.tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)];
	[self addGestureRecognizer:self.tapRecognizer];
    //self.tapRecognizer = (UITapGestureRecognizer *)recognizer;
	self.tapRecognizer.numberOfTouchesRequired = 1;
    self.tapRecognizer.delegate = self;
	//[recognizer release];
	
	//recognizer für taps mit zwei Finger
	self.tapRecTwoFingers = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)];
	[self addGestureRecognizer:self.tapRecTwoFingers];
    //self.tapRecTwoFingers = (UITapGestureRecognizer *)recognizer;
	self.tapRecTwoFingers.numberOfTouchesRequired = 2;
    self.tapRecTwoFingers.delegate = self;
	//[recognizer release];
	
	//recognizer für longpress (touch & hold)
	self.longPressRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleLongPress:)];
	[self addGestureRecognizer:self.longPressRecognizer];
	//self.longPressRecognizer = (UILongPressGestureRecognizer *) recognizer;
	self.longPressRecognizer.delegate = self;
	//[recognizer release];
	
	//recognizer für pans -> dragging
	self.panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)];
	[self addGestureRecognizer:self.panRecognizer];
	//self.panRecognizer = (UIPanGestureRecognizer *)recognizer;
	self.panRecognizer.maximumNumberOfTouches = 2;
	self.panRecognizer.delegate = self;
	//[recognizer release];
	 
	//recognizer für Rotations
	self.rotationRecognizer = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(handleRotation:)];
	[self addGestureRecognizer:self.rotationRecognizer];
	//self.rotationRecognizer = (UIRotationGestureRecognizer *)recognizer;
	self.rotationRecognizer.delegate = self;
	//[recognizer release];
	
	//recognizer für pinches -> skalieren
	self.pinchRecognizer = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(handlePinch:)];
	[self addGestureRecognizer:self.pinchRecognizer];
	//self.pinchRecognizer = (UIPinchGestureRecognizer *)recognizer;
	self.pinchRecognizer.delegate = self;
	//[recognizer release];
	
	
	
	return self;
}

- (void) dealloc {
	
	[tapRecognizer release];
	[tapRecTwoFingers release];
	[longPressRecognizer release];
	[panRecognizer release];
	[rotationRecognizer release];
	[pinchRecognizer release];
	[super dealloc];
	
}

@end
